package com.webex.ta.hydra.core.control;

import com.webex.ta.hydra.core.AbstractController;
import com.webex.ta.hydra.core.Command;
import com.webex.ta.hydra.core.Controller;
import com.webex.ta.hydra.core.ParamDescriptor;
import com.webex.ta.hydra.util.HydraUtils;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by IntelliJ IDEA.
 * User: vegaz
 * Date: 2010-8-19
 * Time: 16:57:19
 * To change this template use File | Settings | File Templates.
 */
public class GenericController extends AbstractController {
    protected transient List<Command> subCommands = new ArrayList<Command>();

    protected transient int current;

    private transient boolean done;
    private transient boolean first = true;

    public ParamDescriptor[] getParamDescriptors(Command cmd) {
        return EMPTY_PARAMDESC;
    }

    public boolean isDone() {
//        System.out.println("CALLING isDone on " + this );
        return done;
    }

    public Command next() {
        Command returnValue = null;
        Command currentCommand = null;
        if (!isDone()) {
            try {
                currentCommand = getCurrentCommand();
                if (currentCommand == null) {
                    // incrementCurrent();
                    returnValue = nextIsNull();
                } else {
                    if (!currentCommand.isEnabled()) {
                        incrementCurrent();
                        return next();
                    }
                    if (HydraUtils.isController(currentCommand)) {
                        GenericController gc = (GenericController)currentCommand.getRuntime();
                        if (gc.isFirst()) {
                            gc.initialize();
                        }
//                        gc.evaluate();
                        returnValue = nextIsAController((Controller) currentCommand.getRuntime());
                    } else {
                        returnValue = nextIsAnAction(currentCommand);
                    }
                }
            } catch (NextIsNullException e) {
                returnValue = null;
            }
        }

        if (returnValue != null) {
		    if (isFirst()) {
			    first = false;
		    }
        }
        return returnValue;
    }

    public void addSubCommand(Command cmd) {
        subCommands.add(cmd);
    }

    protected void removeCurrentElement() {
        subCommands.remove(current);
    }

    protected void resetCurrent() {
        current = 0;
    }

    protected void incrementCurrent() {
        current++;
    }

    protected void setDone(boolean done) {
        this.done = done;
    }

    protected boolean isFirst() {
		return first;
	}

	public void setFirst(boolean b) {
		first = b;
	}

    protected void reInitialize() {
        resetCurrent();
//		incrementIterCount();
		setFirst(true);
//		recoverRunningVersion();
    }

    protected Command getCurrentCommand() throws NextIsNullException {
        if (current < subCommands.size()) {
            return subCommands.get(current);
        } else {
            if (subCommands.size() == 0) {
                setDone(true);
                throw new NextIsNullException();
            }
            return null;
        }
    }


    protected Command nextIsAController(Controller controller) throws NextIsNullException {
        Command returnValue;
        Command sampler = controller.next();
        if (sampler == null) {
//            currentReturnedNull(controller);
//            if (controller.isDone()) {
//                removeCurrentElement();
//            } else {
                incrementCurrent();
//            }
            returnValue = next();
        } else {
            returnValue = sampler;
        }
        return returnValue;
    }

    protected void currentReturnedNull(Controller c) {

    }

    protected Command nextIsNull() throws NextIsNullException {
        reInitialize();
        return null;
    }

    protected Command nextIsAnAction(Command cmd) throws NextIsNullException {
        incrementCurrent();
        return cmd;
    }

    public void initialize() {

    }

}
